package com.cn.demo.aop;

import com.cn.demo.annotation.GuavaRateLimiter;
import com.cn.demo.util.R;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * GuavaRateLimiter注解切面
 *
 * @author wangjf
 * @version 1.0
 * @createDate 2019/11/28 14:46
 * @projectName demo
 */
@Slf4j
@Component
@Aspect
public class GuavaRateLimiterAspect {

    private RateLimiter rateLimiter = RateLimiter.create(Double.MAX_VALUE);

    @Around("@annotation(com.cn.demo.annotation.GuavaRateLimiter)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("拦截到了{}.{}方法...", joinPoint.getTarget().getClass().getSimpleName(), joinPoint.getSignature().getName());
        Object obj = null;
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method targetMethod = methodSignature.getMethod();

        if (targetMethod.isAnnotationPresent(GuavaRateLimiter.class)) {
            GuavaRateLimiter rateLimit = targetMethod.getAnnotation(GuavaRateLimiter.class);
            rateLimiter.setRate(rateLimit.permitsPerSecond());
            if (!rateLimiter.tryAcquire(rateLimit.timeOut(), rateLimit.timeOutUnit())) {
                log.info("=====    接口并发量过大    =====");
                return R.failed("接口达到了最大并发");
            } else {
                obj = joinPoint.proceed();
            }
        }
        return obj;
    }

}
